home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devBlockDevice.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  9KB  |  280 lines

  1. /* 
  2.  * devBlockDevice.c --
  3.  *
  4.  *    Routines supporting the interface to Sprite block devices.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devBlockDevice.c,v 9.2 91/08/19 13:39:20 jhh Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20.  
  21. #include <sprite.h>
  22. #include <fs.h>
  23. #include <devBlockDevice.h>
  24. #include <devFsOpTable.h>
  25. #include <sync.h>
  26.  
  27. static void syncDoneProc _ARGS_((DevBlockDeviceRequest *requestPtr,
  28.     ReturnStatus status, int amountTransferred));
  29.  
  30.  
  31. /*
  32.  *----------------------------------------------------------------------
  33.  *
  34.  * Dev_BlockDeviceAttach --
  35.  *
  36.  *    Build data structures necessary for accessing a block device.
  37.  *    This routine interprets the type field of the Fs_Device structure
  38.  *    and calls the appropriate attach routine. 
  39.  *
  40.  * Results:
  41.  *    A pointer to a DevBlockDeviceHandle structure for the device. 
  42.  *    NIL if the device can not be attached.
  43.  *
  44.  * Side effects:
  45.  *    Device dependent.
  46.  *
  47.  *----------------------------------------------------------------------
  48.  */
  49. DevBlockDeviceHandle *
  50. Dev_BlockDeviceAttach(devicePtr)
  51.     Fs_Device    *devicePtr;    /* The device to attach. */
  52. {
  53.  
  54.     int    type = DEV_TYPE_INDEX(devicePtr->type);
  55.     /*
  56.      * If type is out of range or the device type as no block IO 
  57.      * capabilities then give up. Otherwise we let the Device Attach
  58.      * procedure file the device.
  59.      */
  60. #ifndef lint
  61.     if ((type >= devNumDevices) ||
  62.     (devFsOpTable[type].blockDevAttach == DEV_NO_ATTACH_PROC)) {
  63.     return ((DevBlockDeviceHandle *) NIL);
  64.     }
  65. #endif
  66.     return ((devFsOpTable[type].blockDevAttach)(devicePtr));
  67. }
  68.  
  69.  
  70. /*
  71.  *----------------------------------------------------------------------
  72.  *
  73.  * Dev_BlockDeviceRelease --
  74.  *
  75.  *    Release an attached block device. Resources held by the device 
  76.  *    should be freed.
  77.  *
  78.  * Results:
  79.  *    A Sprite return Status specifying it the device could be releases.
  80.  *
  81.  * Side effects:
  82.  *    Device dependent.
  83.  *
  84.  *----------------------------------------------------------------------
  85.  */
  86. ReturnStatus
  87. Dev_BlockDeviceRelease(blockDevHandlePtr)
  88.      DevBlockDeviceHandle
  89.         *blockDevHandlePtr;  /* Handle of the device to releaes */
  90. {
  91.     return (blockDevHandlePtr->releaseProc)(blockDevHandlePtr);
  92.  
  93. }
  94.  
  95.  
  96. /*
  97.  *----------------------------------------------------------------------
  98.  *
  99.  * Dev_BlockDeviceIO --
  100.  *
  101.  *    Enqueue a block IO request for the specified device. Upon operation
  102.  *    completion doneProc will be called. 
  103.  *
  104.  *     NOTE: The DevBlockDeviceRequest structure pointed to by the requestPtr
  105.  *          argument is assumed to remain valid and unchanged until the
  106.  *          doneProc specified in DevBlockDeviceRequest is called.
  107.  *
  108.  * Results:
  109.  *    SUCCESS if operation is sucessfully enqueued. 
  110.  *    A Sprite error code otherwise.
  111.  *
  112.  * Side effects:
  113.  *    The specified doneProc is called with the following arguments:
  114.  *
  115.  *    (*doneProc)(requestPtr, returnStatus, amountTransferred)
  116.  *        DevBlockDeviceRequest    *requestPtr;   
  117.  *                           / * The requestPtr passed to
  118.  *                         * Dev_BlockDeviceIO. * /
  119.  *        ReturnStatus    returnStatus;  / * The error status of the
  120.  *                         * command. SUCCESS if no
  121.  *                         * error occured. * /
  122.  *        int    amountTransferred;     / * The number of blocks
  123.  *                         * transfered by the 
  124.  *                         * operation. * /
  125.  *----------------------------------------------------------------------
  126.  * Because of its simplicity and in an attempt to reduce procedure calling
  127.  * depth, Dev_BlockDeviceIO may be coded as an macro in devBlockDevice.h.
  128.  */
  129. #ifndef Dev_BlockDeviceIO
  130. ReturnStatus 
  131. Dev_BlockDeviceIO(blockDevHandlePtr, requestPtr)
  132.     DevBlockDeviceHandle
  133.         *blockDevHandlePtr;  /* Handle of the device to operate on. */
  134.     DevBlockDeviceRequest
  135.         *requestPtr;         /* Request to be performed. */
  136. {
  137.     return (blockDevHandlePtr->blockIOProc)(blockDevHandlePtr, requestPtr);
  138. }
  139. #endif /* Dev_BlockDeviceIO */
  140.  
  141. /*
  142.  *----------------------------------------------------------------------
  143.  *
  144.  * Dev_BlockDeviceIOControl --
  145.  *
  146.  *    Execute an IO control operation on the specified device.
  147.  *
  148.  * Results:
  149.  *    SUCCESS if operation is successful. 
  150.  *    An error status otherwise.
  151.  *
  152.  * Side effects:
  153.  *    Device dependent.
  154.  *
  155.  *----------------------------------------------------------------------
  156.  * Because of its simplicity and in an attempt to reduce procedure calling
  157.  * depth, Dev_BlockDeviceIOControl may be coded as an macro in devBlockDevice.h.
  158.  */
  159. #ifndef    Dev_BlockDeviceIOControl
  160. ReturnStatus 
  161. Dev_BlockDeviceIOControl(blockDevHandlePtr, ioctlPtr, replyPtr) 
  162.     DevBlockDeviceHandle
  163.         *blockDevHandlePtr;  /* Handle of the device to operate on. */
  164.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  165.     Fs_IOReply *replyPtr;    /* outBuffer length and returned signal */
  166. {
  167.  
  168.     return (blockDevHandlePtr->IOControlProc)(blockDevHandlePtr, ioctlPtr, replyPtr);
  169.  
  170.  
  171. }
  172. #endif /* Dev_BlockDeviceIOControl */
  173. /*
  174.  * The following structure and routines are used to implement the routine
  175.  * Dev_BlockDeviceIOSync.
  176.  * The arguments to Dev_BlockDeviceIOSync are stored in a SyncCmdBuf on 
  177.  * the caller's stack and  Dev_BlockDeviceIO is called. The call back function
  178.  * syncDoneProc fills in the OUT arguments are wakes the caller.
  179.  *
  180.  */
  181. typedef struct SyncCmdBuf {
  182.     Sync_Semaphore mutex;      /* Lock for synronizing updates of 
  183.                    * this structure with the call back 
  184.                    * function. */
  185.     Sync_Condition wait;      /* Condition valued used to wait for
  186.                    * callback. */
  187.     Boolean      done;          /* Is the operation finished or not? */
  188.     int      amountTransferred;       /* Number of bytes transferred according
  189.                    * to the call back. */
  190.     ReturnStatus status;       /* Operation return status according to 
  191.                    * call back. */
  192. } SyncCmdBuf;
  193.  
  194. /*
  195.  *----------------------------------------------------------------------
  196.  *
  197.  * syncDoneProc --
  198.  *
  199.  *    This procedure is called when a sync block command started by 
  200.  *    Dev_BlockDeviceIO finished. It's calling sequence is 
  201.  *    defined by the call back caused by the Dev_BlockDeviceIO routine.
  202.  *
  203.  * Results:
  204.  *    None.
  205.  *
  206.  * Side effects:
  207.  *    SyncCmdBuf is filled in and a wakeup is broadcast.
  208.  *
  209.  *----------------------------------------------------------------------
  210.  */
  211.  
  212. static void
  213. syncDoneProc(requestPtr, status, amountTransferred)
  214.     DevBlockDeviceRequest    *requestPtr;
  215.     ReturnStatus status;
  216.     int    amountTransferred;
  217. {
  218.     SyncCmdBuf    *syncCmdDataPtr = (SyncCmdBuf *) (requestPtr->clientData);
  219.     /*
  220.      * A pointer to a SyncCmdBuf is passed as the clientData to this call.
  221.      * Lock the structure, fill in the return values and wake up the
  222.      * initiator.
  223.      */
  224.     MASTER_LOCK(&syncCmdDataPtr->mutex);
  225.     syncCmdDataPtr->status = status;
  226.     syncCmdDataPtr->amountTransferred = amountTransferred;
  227.     syncCmdDataPtr->done = TRUE;
  228.     Sync_MasterBroadcast(&syncCmdDataPtr->wait);
  229.     MASTER_UNLOCK(&syncCmdDataPtr->mutex);
  230.     return;
  231. }
  232.  
  233. /*
  234.  *----------------------------------------------------------------------
  235.  *
  236.  * Dev_BlockDeviceIOSync --
  237.  *
  238.  *    Perform a block IO request for the specified device and wait 
  239.  *    for completion.
  240.  *
  241.  * Results:
  242.  *    SUCCESS if operation is successful completed. 
  243.  *    A Sprite error code otherwise.
  244.  *
  245.  * Side effects:
  246.  *    Device specific block IO done.
  247.  *----------------------------------------------------------------------
  248.  */
  249. ReturnStatus 
  250. Dev_BlockDeviceIOSync(blockDevHandlePtr, requestPtr,amountTransferredPtr)
  251.     DevBlockDeviceHandle
  252.         *blockDevHandlePtr;  /* Handle of the device to operate on. */
  253.     DevBlockDeviceRequest 
  254.         *requestPtr;         /* Request to block IO device. */
  255.     int    *amountTransferredPtr;          /* Area to store number of bytes
  256.                       * transferred. May be NIL. */
  257. {
  258.     ReturnStatus status;
  259.     SyncCmdBuf     syncCmdData;
  260.  
  261.     requestPtr->clientData = (ClientData) &syncCmdData;
  262.     requestPtr->doneProc = syncDoneProc;
  263.     Sync_SemInitDynamic((&syncCmdData.mutex),"BlockSyncCmdMutex");
  264.     syncCmdData.done = FALSE;
  265.     syncCmdData.amountTransferred = 0;
  266.     status = Dev_BlockDeviceIO(blockDevHandlePtr, requestPtr);
  267.     if (status == SUCCESS) {
  268.     MASTER_LOCK((&syncCmdData.mutex));
  269.     while (syncCmdData.done == FALSE) { 
  270.         Sync_MasterWait((&syncCmdData.wait),(&syncCmdData.mutex),FALSE);
  271.     }
  272.     MASTER_UNLOCK((&syncCmdData.mutex));
  273.     status = syncCmdData.status;
  274.     } 
  275.     if (amountTransferredPtr != (int *) NIL) { 
  276.     *amountTransferredPtr = syncCmdData.amountTransferred;
  277.     }
  278.     return (status);
  279. }
  280.